/*
 *  All common operations should be here!
 *  Use only the image read from this class all scale and other
 *  common operations are implemented in this class.
 *
 *  All common parameters that are used in more than one file
 *  should be declared and defined here.
 *
 *  All functions in this class should be static
 */

#ifndef DEEPDR_COMMON_H
#define DEEPDR_COMMON_H

#define BACKWARD_HAS_BFD 1
#define BACKWARD_HAS_DW 1


#include <time.h>
#include <opencv/cv.h>
#include <sstream>
#include <execinfo.h>
#include <boost/filesystem/operations.hpp>
#include "backward.hpp"
#include <primesieve.hpp>
#include <gtest/gtest.h>
#include <glog/logging.h>

using cv::Mat;
using std::string;
using std::stringstream;
using boost::filesystem::exists;
using boost::filesystem::create_directories;
using boost::filesystem::path;
using google::INFO;
using google::WARNING;
using google::ERROR;
using google::FATAL;

class Common {
public:
    static string tostring(int i) {
        stringstream ss;
        ss << i;
        string retval = ss.str();
        return retval;
    }

    static string printTrace() {
        using namespace backward;
        StackTrace st;
        st.load_here(32);
        Printer p;
        p.object = true;
        p.color = true;
        p.address = true;
        p.snippet = true;
        p.print(st);
        return "\n";
    }

};

/*
 * This class permute an array of 0~~size-1.
 * By the face that i * prime % size permute
 * the array.
 * The start of permutation is random.
 * And the prime number is also selected as a
 * random one.
 * So this class provide a random permutation
 * that behaviors randomly.
 */
class Permutation {
    uint64_t prime;
    uint64_t size;
    uint64_t current_;
    uint64_t counter;
public:
    Permutation(int size_) : size((uint64_t) size_) {
        CHECK_GE(size_, 0) <<
                           Common::printTrace() <<
                           "Error, size must be a positive number";
        primesieve::iterator pi;
        pi.skipto(rand() % size + size);
        prime = pi.next_prime();
        current_ = rand() % size;
        counter = 0;
    }

    int current() {
        return (int) current_;
    }

    int next() {
        if (counter > size) {
            LOG(ERROR) << "Permutation overlapped";
        }
        current_ += prime;
        current_ %= size;
        return (int) current_;
    }
};

class PerformanceMeasure {
    bool counting;
    clock_t beginTime;
    clock_t endTime;
    clock_t counter;
public:
    PerformanceMeasure();

    void begin();

    void reset();

    void end();

    double getPeriod();
};


#endif //DEEPDR_COMMON_H
